package com.example.app;

import java.net.InetSocketAddress;

import net.sf.calibur.engine.CaliburEngine;
import net.sf.calibur.engine.Event;
import net.sf.calibur.engine.EventRouter;
import net.sf.calibur.engine.Executor;
import net.sf.calibur.engine.ExecutorPool;
import net.sf.calibur.jmx.JmxRegister;
import net.sf.calibur.jmx.ManagedBean;
import net.sf.calibur.monitor.FileSystemMonitor;
import net.sf.calibur.pool.KeyedObjectPool;
import net.sf.calibur.transport.CommandMessageEvent;
import net.sf.calibur.transport.Session;
import net.sf.calibur.transport.SessionManager;
import net.sf.calibur.transport.Transporter;
import net.sf.calibur.transport.mina.MinaTcpTransporter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.example.app.handler.MapCommandHandler;
import com.example.app.handler.MissionCommandHandler;
import com.example.app.handler.PlayerManagementCommandHandler;
import com.example.app.messagebean.ObjectFactory;

public class Main {
	private AppContext ctx = AppContext.getInstance();
	private CaliburEngine engine;
	private Transporter transporter;
	private Logger logger = LoggerFactory.getLogger("MAIN");

	public Main() {
		JmxRegister.register(KeyedObjectPool.init());
		ctx.setMessageBeanFactory(ObjectFactory.getInstance());
		engine = new CaliburEngine("DemoGame");
		ctx.setEngine(engine);
	}

	public void init() throws Exception {
		// 初始化对象池
		KeyedObjectPool.getInstance().addStackElementFilter(
				Main.class.getPackage().getName());

		// 监听config目录下文件的改变
		try {
			FileSystemMonitor monitor = new FileSystemMonitor(engine);
			monitor.watchDirectory("config");
		} catch (Throwable t) {
			logger.error("Monitor directory failed.", t);
		}

		// 玩家实例管理线程池，处理用户login、logout，这些处理比较费时
		EventRouter router = new EventRouter() {
			@Override
			public Executor route(Event event, ExecutorPool pool) {
				return pool.getMinLoadExecutor();
			}
		};
		engine.addExecutorPool("playerManagementLane", 4, router,
				new PlayerManagementCommandHandler());

		// 快速指令执行线程池，处理的指令都是已经成功登录了的玩家行为相关指令。
		router = new EventRouter() {
			@Override
			public Executor route(Event event, ExecutorPool pool) {
				CommandMessageEvent cme = (CommandMessageEvent) event;
				Session session = cme.getSession();
				Player player = (Player) session
						.getAttribute(AppContext.ATTR_PLAYER);
				int idx = (int) (player.getId() % pool.getSize());
				return pool.getExecutor(idx);
			}
		};
		engine.addExecutorPool("fastLane", 4, router,
				new MapCommandHandler(), new MissionCommandHandler());

		// 增加网络端口监听
		transporter = new MinaTcpTransporter("MINA-TCP-10000",
				new InetSocketAddress(10000), new SessionManager(engine,
						ctx.getMessageBeanFactory()));
		JmxRegister.register((ManagedBean) transporter);
	}

	/**
	 * 启动引擎
	 */
	public void start() {
		try {
			logger.info("Starting ...");
			engine.start();
			transporter.start();
		} catch (Throwable t) {
			logger.error("Start engine failed.", t);
			System.exit(1);
		}
	}

	public static void main(String[] args) {
		Main application = new Main();

		try {
			application.init();
		} catch (Exception e) {
			System.err.println("Initialize failed. ");
			e.printStackTrace();
			System.exit(1);
		}

		application.start();
	}
}
